/******************************************************
*  Copyright(c) pages.ilovezxl.top
*  FileName :cli_tty_socket.c
*  Author : rivulet.dave
*  Description : shellÊäÈë£¬Êä³ö
*  Data : 2020-07-19
******************************************************/

/*********************************************************************
 * INCLUDES
 */

#include "stdrope.h"
#include "sallib.h"

#if (SAL_CLI == _ENABLE && SAL_TTY_PRODUCER == _TTY_SOCK_)

#include "salagent.h"
#include "anysock.h"

#include "cli_tty.h"
#include "cli_tty_socket.h"

/*********************************************************************
 *  EXTERNAL VARIABLES
 */

/*********************************************************************
 * MACROS
 */

#define TTY_SERVER_PORT 8387
#define TTY_BUFF_LEN    256

/*********************************************************************
 * TYPES
 */

typedef struct _tty_socket_cb
{
    int32_t iSockFd;
    struct sockaddr_in stClientAddr;
} TTY_SOCK_CB_S;

/*********************************************************************
 * FUNCTIONS DECLARE
 */

static void TTY_SocketInit(void);
static void TTY_SocketDeInit(void);
static int32_t TTY_SocketGets(char *pData, uint32_t uiLen);
static int32_t TTY_SocketPuts(char *pData, uint32_t uiLen);

/*********************************************************************
 *  VARIABLES
 */

static TTY_SOCK_CB_S s_stTTYSockCb = {.iSockFd = -1};
static TTY_BASE_S s_stTTYSocketObject;

/*********************************************************************
 * FUNCTIONS
 */

/**
 *   @Description: TTY Socket对象创建
 *   @param : NA
 *   @return: TTY_BASE_S
 */
TTY_BASE_S *TTY_SocketObjNew(void)
{
    TTY_SocketInit();
    s_stTTYSocketObject.pfTTYGets = TTY_SocketGets;
    s_stTTYSocketObject.pfTTYPuts = TTY_SocketPuts;
    return &s_stTTYSocketObject;
}

/**
 *   @Description: TTY Socket对象删除
 *   @param : NA
 *   @return: TTY_BASE_S
 */
void TTY_SocketObjDel(void)
{
    TTY_SocketDeInit();
}

/**
 *   @Description: TTY Socket初始化
 *   @param : NA
 *   @return: NA
 */
static void TTY_SocketInit(void)
{
    struct sockaddr_in serv_addr;

    s_stTTYSockCb.iSockFd = socket(AF_INET, SOCK_DGRAM, 0);
    if (0 > s_stTTYSockCb.iSockFd)
    {
        return;
    }

    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址，需要进行网络序转换，INADDR_ANY：本地地址
    serv_addr.sin_port = htons(TTY_SERVER_PORT);  //端口号，需要网络序转换

    if (0 > bind(s_stTTYSockCb.iSockFd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)))
    {
        return;
    }
}

/**
 *   @Description: TTY Socket去初始化
 *   @param : NA
 *   @return: NA
 */
static void TTY_SocketDeInit(void)
{
    close(s_stTTYSockCb.iSockFd);
}

/**
 *   @Description: 通过Socket获取命令行
 *   @param : pData - 出参，命令行数据
 *   @param : uiLen - 入参，缓存长度
 *   @return: _OK/_ERR
 */
static int32_t TTY_SocketGets(char *pData, uint32_t uiLen)
{
    int32_t iRecvLen = 0;
    socklen_t iLen = 0;

    if (!pData)
    {
        return _ERR;
    }

    iLen = sizeof(struct sockaddr);
    iRecvLen = recvfrom(s_stTTYSockCb.iSockFd, pData, uiLen, 0, (struct sockaddr*)&s_stTTYSockCb.stClientAddr, &iLen);
    return iRecvLen;
}

/**
 *   @Description: 通过Socket发送命令
 *   @param : pData - 入参，发送的命令行数据
 *   @param : uiLen - 入参，数据长度
 *   @return: _OK/_ERR
 */
static int32_t TTY_SocketPuts(char *pData, uint32_t uiLen)
{
    socklen_t iLen = 0;
    int32_t iSendLen = 0;

    if (!pData)
    {
        return _ERR;
    }

    if (0 > s_stTTYSockCb.iSockFd)
    {
        return _ERR;
    }

    iLen = sizeof(struct sockaddr);
    iSendLen = sendto(s_stTTYSockCb.iSockFd, pData, uiLen, 0, (struct sockaddr*)&s_stTTYSockCb.stClientAddr, iLen);
    return iSendLen;
}

#endif  //(SAL_CLI == _ENABLE && SAL_TTY_PRODUCER == _TTY_SOCK_)


